/*
 * @Author: WangShuai 1830773767@qq.com
 * @Date: 2025-05-07 21:09:45
 * @LastEditors: WangShuai 1830773767@qq.com
 * @LastEditTime: 2025-05-10 17:39:20
 * @FilePath: \Webgl-basic\src\6.绘制正三角形.js
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
import {
    initShader,
    createBuffer,
    createCubeGem
} from '../lib/index'
import {
    mat4
} from 'gl-matrix';
import * as dat from 'dat.gui'
const canvas = document.querySelector('canvas')
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
//获取webgl上下文
const gl = canvas.getContext('webgl')
//定义点顶点着色器(字符串)
const vs_shader = /*glsl*/ `
  // 指定浮点数精度为中等精度  
  precision mediump float;//glsl语法每一行后面都要加上分号,每一行后面都要加上分号
  attribute vec3 a_Position;
  attribute vec3 a_Color;
  varying vec3 v_Color;
  uniform mat4 u_ViewMatrix;
  uniform mat4 u_ProjMatrix;
  uniform mat4 u_ModelMatrix;
  //glsl语法中,必须有一个入口函数main shaderToy里面叫mainImage cesuim里面可能叫czm_Main
  void main(){
    //gl_Position 是最后输出的坐标值,Vect4是四维向量,具有四个分量,每一个分量都是float
    // gl_Position= vec4(a_Position,1.0);
    gl_Position= u_ProjMatrix * u_ViewMatrix * u_ModelMatrix * vec4(a_Position,1.0);
    v_Color= a_Color;
  }`
//片元着色器
const fs_shader = /*glsl*/ `
precision mediump float;
varying vec3 v_Color;
void main(){
    //gl_FragColor是最后输出的像素颜色,是一个四维的数据
    gl_FragColor = vec4(v_Color,1.0);            
}`
//编译着色器,生成程序对象  操作手，专门负责javaScript和shader着色器的通讯
const program = initShader(gl, vs_shader, fs_shader)
gl.program = program;


//视点位置
const viewObj = {
    eyeX: 3,
    eyeY: 3,
    eyeZ: 8,
    lookAtX: 0,
    lookAtY: 0,
    lookAtZ: 0,
    fov: 38,
    near: 0.2,
    far: 100,
    rotationSpeedX: 0.01, // X轴旋转速度
    rotationSpeedY: 0.01, // Y轴旋转速度
    rotationSpeedZ: 0.0, // Z轴旋转速度
    autoRotate: true // 是否自动旋转
};

// 旋转角度
let rotationX = 0;
let rotationY = 0;
let rotationZ = 0;

// 上一帧的时间戳
let lastTime = 0;

// 模型矩阵
let modelMatrix = mat4.create();

const renderView = (currentTime) => {
    // 计算时间差，用于平滑动画
    if (lastTime === 0) {
        lastTime = currentTime;
    }
    const deltaTime = currentTime - lastTime;
    lastTime = currentTime;

    // 更新旋转角度
    if (viewObj.autoRotate) {
        rotationX += viewObj.rotationSpeedX * deltaTime;
        rotationY += viewObj.rotationSpeedY * deltaTime;
        rotationZ += viewObj.rotationSpeedZ * deltaTime;
    }

    // 更新模型矩阵
    updateModelMatrix();

    renderProMatrix();
    renderViewMatrix();
    renderModelMatrix();

    const n = createCube();
    gl.clearColor(0.0, 0.0, 0.0, 1.0);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    gl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_BYTE, 0);

    // 请求下一帧
    requestAnimationFrame(renderView);
}

const updateModelMatrix = () => {
    // 重置模型矩阵
    mat4.identity(modelMatrix);

    // 应用旋转变换
    mat4.rotateX(modelMatrix, modelMatrix, rotationX);
    mat4.rotateY(modelMatrix, modelMatrix, rotationY);
    mat4.rotateZ(modelMatrix, modelMatrix, rotationZ);
}

const renderProMatrix = () => {
    const u_ProjMatrix = gl.getUniformLocation(program, 'u_ProjMatrix')
    //创建正射投影矩阵
    let projMatrix = mat4.create();
    // console.log("projMatrix1", projMatrix);
    mat4.identity(projMatrix);
    //使用透视投影矩阵
    projMatrix = mat4.perspectiveNO(projMatrix, viewObj.fov * Math.PI / 180, window.innerWidth / window.innerHeight, viewObj.near, viewObj.far)
    // console.log("projMatrix2", projMatrix);
    gl.uniformMatrix4fv(u_ProjMatrix, false, projMatrix);
}

const renderViewMatrix = () => {
    const u_ViewMatrix = gl.getUniformLocation(program, 'u_ViewMatrix')
    //创建视图矩阵
    let viewMatrix = mat4.create();
    mat4.identity(viewMatrix);
    viewMatrix = mat4.lookAt(viewMatrix, [viewObj.eyeX, viewObj.eyeY, viewObj.eyeZ], [viewObj.lookAtX, viewObj.lookAtY, viewObj.lookAtZ], [0, 1, 0])
    gl.uniformMatrix4fv(u_ViewMatrix, false, viewMatrix);
}

const renderModelMatrix = () => {
    const u_ModelMatrix = gl.getUniformLocation(program, 'u_ModelMatrix');
    gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix);
}

// 创建正方体函数
const createCube = () => {
    const {
        vertices,
        colors,
        indices
    } = getData();

    const config = new Map()
    config.set("a_Position", vertices);
    config.set("a_Color", colors);

    // 封装正方体的buffer
    const n = createCubeGem(gl, indices, config, {
        size: 3
    });

    // 开启隐藏面剔除
    gl.enable(gl.DEPTH_TEST);

    return n;
}

// 开始动画循环
requestAnimationFrame(renderView);

// 数据获取函数
const getData = () => {
    // Create a cube
    //    v6----- v5
    //   /|      /|
    //  v1------v0|
    //  | |     | |
    //  | |v7---|-|v4
    //  |/      |/
    //  v2------v3
    var vertices = new Float32Array([ // Vertex coordinates
        1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, // v0-v1-v2-v3 front
        1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, // v0-v3-v4-v5 right
        1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, // v0-v5-v6-v1 up
        -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, // v1-v6-v7-v2 left
        -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0, // v7-v4-v3-v2 down
        1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0 // v4-v7-v6-v5 back
    ]);

    var colors = new Float32Array([ // Colors
        0.4, 0.4, 1.0, 0.4, 0.4, 1.0, 0.4, 0.4, 1.0, 0.4, 0.4, 1.0, // v0-v1-v2-v3 front(blue)
        0.4, 1.0, 0.4, 0.4, 1.0, 0.4, 0.4, 1.0, 0.4, 0.4, 1.0, 0.4, // v0-v3-v4-v5 right(green)
        1.0, 0.4, 0.4, 1.0, 0.4, 0.4, 1.0, 0.4, 0.4, 1.0, 0.4, 0.4, // v0-v5-v6-v1 up(red)
        1.0, 1.0, 0.4, 1.0, 1.0, 0.4, 1.0, 1.0, 0.4, 1.0, 1.0, 0.4, // v1-v6-v7-v2 left
        1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, // v7-v4-v3-v2 down
        0.4, 1.0, 1.0, 0.4, 1.0, 1.0, 0.4, 1.0, 1.0, 0.4, 1.0, 1.0 // v4-v7-v6-v5 back
    ]);

    var indices = new Uint8Array([ // Indices of the vertices
        0, 1, 2, 0, 2, 3, // front
        4, 5, 6, 4, 6, 7, // right
        8, 9, 10, 8, 10, 11, // up
        12, 13, 14, 12, 14, 15, // left
        16, 17, 18, 16, 18, 19, // down
        20, 21, 22, 20, 22, 23 // back
    ]);

    return {
        vertices,
        colors,
        indices
    }
}

// 更新GUI
const gui = new dat.GUI();
const projFolder = gui.addFolder('proj');
projFolder.add(viewObj, 'near', -1, 1, 0.01).onChange(renderProMatrix);
projFolder.add(viewObj, 'far', -1, 2, 0.01).onChange(renderProMatrix);
projFolder.add(viewObj, 'fov', 0, 90, 0.1).onChange(renderProMatrix);

const eyeFolder = gui.addFolder('eyePosition');
eyeFolder.add(viewObj, 'eyeX', -10, 10, 0.01).onChange(renderViewMatrix);
eyeFolder.add(viewObj, 'eyeY', -10, 10, 0.01).onChange(renderViewMatrix);
eyeFolder.add(viewObj, 'eyeZ', -10, 10, 0.01).onChange(renderViewMatrix);

const lookAtFolder = gui.addFolder('lookPostion');
lookAtFolder.add(viewObj, 'lookAtX', -1, 1, 0.01).onChange(renderViewMatrix);
lookAtFolder.add(viewObj, 'lookAtY', -1, 1, 0.01).onChange(renderViewMatrix);
lookAtFolder.add(viewObj, 'lookAtZ', -1, 1, 0.01).onChange(renderViewMatrix);

const rotateFolder = gui.addFolder('rotation');
rotateFolder.add(viewObj, 'autoRotate').onChange(() => {
    // 重置时间戳
    lastTime = 0;
});
rotateFolder.add(viewObj, 'rotationSpeedX', -0.05, 0.05, 0.001);
rotateFolder.add(viewObj, 'rotationSpeedY', -0.05, 0.05, 0.001);
rotateFolder.add(viewObj, 'rotationSpeedZ', -0.05, 0.05, 0.001);